//跟Selector有关的对Document和Element的扩展实现
Native.implement([Document, Element], {
 

 //根据查询表达式获取子节点
 getElements: function(expression, nocash){
  //拆分查询表达式
  expression = expression.split(',');
  var items, local = {};
  for (var i = 0, l = expression.length; i < l; i++){
   //根据查询条件搜索匹配的节点
   var selector = expression[i], elements = Selectors.Utils.search(this, selector, local);
   //如果找到节点集合,转为数组类型
   if (i != 0 && elements.item) elements = $A(elements);
   //加到items数组中
   items = (i == 0) ? elements : (items.item) ? $A(items).concat(elements) : items.concat(elements);
  }
  //返回Elements集合
  return new Elements(items, {ddup: (expression.length > 1), cash: !nocash});
 }
 
});

//跟Selector有关的对Element的扩展实现
Element.implement({
 
 //判断当前节点是否匹配指定模式
 match: function(selector){
  if (!selector) return true;
  //根据选择符解释出标签名和id
  var tagid = Selectors.Utils.parseTagAndID(selector);
  var tag = tagid[0], id = tagid[1];
  //当前节点不匹配ID或标签中的任一个都返回false
  if (!Selectors.Filters.byID(this, id) || !Selectors.Filters.byTag(this, tag)) return false;
  //根据选择符匹配
  var parsed = Selectors.Utils.parseSelector(selector);
  return (parsed) ? Selectors.Utils.filter(this, parsed, {}) : true;
 }
 
});

//声明为简单对象,搭个框架等待后续的填充处理
var Selectors = {Cache: {nth: {}, parsed: {}}};

Selectors.RegExps = {
 //查询表达式中对id的匹配模式
 id: (/#([\w-]+)/),
 //查询表达式中对标签名的匹配模式
 tag: (/^(\w+|\*)/),
 //查询表达式中对快速模式的匹配模式
 quick: (/^(\w+|\*)$/),
 //查询表达式中对分隔符的匹配模式
 splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),
 //组合模式 
 combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)
};

//一些辅助的工具方法
Selectors.Utils = {

 //检查item是否重复
 chk: function(item, uniques){
  if (!uniques) return true;
  //总是返回当前元素的唯一id
  var uid = $uid(item);
  //如果不存在,说明集合中还没有此项,置为true返回
  if (!uniques[uid]) return uniques[uid] = true;
  return false;
 },
 
 /*
 解释nth查询时的参数
 nth表示对第n个的查询,见http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#nth-child-pseudo
 */
 parseNthArgument: function(argument){
  //如果曾经按相同参数查询过,返回缓存的结果,不错的策略,避免每次重新计算
  if (Selectors.Cache.nth[argument]) return Selectors.Cache.nth[argument];
  //解释nth查询的参数
  var parsed = argument.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);
  if (!parsed) return false;
  //第一个数值
  var inta = parseInt(parsed[1]);
  //inta没值时a默认为1
  var a = (inta || inta === 0) ? inta : 1;
  //命名部分
  var special = parsed[2] || false;
  //第二个数值
  var b = parseInt(parsed[3]) || 0;
  if (a != 0){
   b--;
   while (b < 1) b += a;
   while (b >= a) b -= a;
  } else {
   a = b;
   special = 'index';
  }
  switch (special){
   case 'n': parsed = {a: a, b: b, special: 'n'}; break;
   case 'odd': parsed = {a: 2, b: 0, special: 'n'}; break;
   case 'even': parsed =  {a: 2, b: 1, special: 'n'}; break;
   case 'first': parsed = {a: 0, special: 'index'}; break;
   case 'last': parsed = {special: 'last-child'}; break;
   case 'only': parsed = {special: 'only-child'}; break;
   default: parsed = {a: (a - 1), special: 'index'};
  }
  
  return Selectors.Cache.nth[argument] = parsed;
 },
 
 //解释选择符
 parseSelector: function(selector){
  //同样的缓存策略
  if (Selectors.Cache.parsed[selector]) return Selectors.Cache.parsed[selector];
  var m, parsed = {classes: [], pseudos: [], attributes: []};
  //注意正则的exec和match的区别
  while ((m = Selectors.RegExps.combined.exec(selector))){
   //匹配结果依次为:CSS类名,属性名,属性操作符,属性值,伪类名,伪类属性
   var cn = m[1], an = m[2], ao = m[3], av = m[4], pn = m[5], pa = m[6];
   if (cn){
    //加到CSS类名集合
    parsed.classes.push(cn);
   } else if (pn){
    var parser = Selectors.Pseudo.get(pn);
    //如果存在伪类名,pa作为伪类参数
    if (parser) parsed.pseudos.push({parser: parser, argument: pa});
    //否则作为属性比较的右值
    else parsed.attributes.push({name: pn, operator: '=', value: pa});
   } else if (an){
    //属性比较
    parsed.attributes.push({name: an, operator: ao, value: av});
   }
  }
  //如果选择符中不存在CSS类名的查询,删除classes属性
  if (!parsed.classes.length) delete parsed.classes;
  //如果选择符中不存在Element属性的查询,删除attributes属性
  if (!parsed.attributes.length) delete parsed.attributes;
  //如果选择符中不存在伪类的查询,删除pseudos属性
  if (!parsed.pseudos.length) delete parsed.pseudos;
  //如果三者都不存在,置null
  if (!parsed.classes && !parsed.attributes && !parsed.pseudos) parsed = null;
  //缓存结果并返回
  return Selectors.Cache.parsed[selector] = parsed;
 },
 
 //解释查询表达式中的标签名和id
 parseTagAndID: function(selector){
  //匹配标签名
  var tag = selector.match(Selectors.RegExps.tag);
  //匹配id
  var id = selector.match(Selectors.RegExps.id);
  //没有匹配标签时用星号'*'代替,没有匹配id时返回false
  return [(tag) ? tag[1] : '*', (id) ? id[1] : false];
 },
 
 filter: function(item, parsed, local){
  var i;
  //根据CSS类名匹配
  if (parsed.classes){
   for (i = parsed.classes.length; i--; i){
    var cn = parsed.classes[i];
    if (!Selectors.Filters.byClass(item, cn)) return false;
   }
  }
  //根据属性匹配
  if (parsed.attributes){
   for (i = parsed.attributes.length; i--; i){
    var att = parsed.attributes[i];
    if (!Selectors.Filters.byAttribute(item, att.name, att.operator, att.value)) return false;
   }
  }
  //根据伪类匹配
  if (parsed.pseudos){
   for (i = parsed.pseudos.length; i--; i){
    var psd = parsed.pseudos[i];
    if (!Selectors.Filters.byPseudo(item, psd.parser, psd.argument, local)) return false;
   }
  }
  return true;
 },
 
 //根据标签名和ID查找Element
 getByTagAndID: function(ctx, tag, id){
  //如果提供id
  if (id){
   //先根据id查找到Element
   var item = ctx.getElementById(id, true);
   //再根据标签名过滤
   return (item && Selectors.Filters.byTag(item, tag)) ? [item] : [];
  } else {
   //不提供id时直接查找满足标签名的Element
   return ctx.getElementsByTagName(tag);
  }
 },
 
 //查找
 search: function(self, expression, local){
  //查询表达式的按分隔符分割出来的操作符
  var splitters = [];
  /*
  根据分隔符切割查询表达式,看来expression中不能包含':)'
  替换函数中m0是整个匹配的字符串,m1为+>~和空白之类的字符,m2为子表达式内容
  */
  var selectors = expression.trim().replace(Selectors.RegExps.splitter, function(m0, m1, m2){
   splitters.push(m1);
   return ':)' + m2;
  }).split(':)');
  
  var items, match, filtered, item;
  
  for (var i = 0, l = selectors.length; i < l; i++){
   
   var selector = selectors[i];
   
   //匹配quick模式意味着可以使用标签名匹配查找
   if (i == 0 && Selectors.RegExps.quick.test(selector)){
    items = self.getElementsByTagName(selector);
    continue;
   }
   
   var splitter = splitters[i - 1];
   
   //解释出标签名和id
   var tagid = Selectors.Utils.parseTagAndID(selector);
   var tag = tagid[0], id = tagid[1];

   if (i == 0){
    //在首位时的处理
    items = Selectors.Utils.getByTagAndID(self, tag, id);
   } else {
    //先按标签名,id和操作符查找所有匹配项
    var uniques = {}, found = [];
    for (var j = 0, k = items.length; j < k; j++) found = Selectors.Getters[splitter](found, items[j], tag, id, uniques);
    items = found;
   }
   
   //根据其它选择符过滤
   var parsed = Selectors.Utils.parseSelector(selector);
   
   if (parsed){
    filtered = [];
    for (var m = 0, n = items.length; m < n; m++){
     item = items[m];
     //过滤匹配
     if (Selectors.Utils.filter(item, parsed, local)) filtered.push(item);
    }
    items = filtered;
   }
  }
  return items;  
 }
};

//根据四种操作符查找
Selectors.Getters = {
 //空格,表示根据标签名和id的常规查找
 ' ': function(found, self, tag, id, uniques){
  var items = Selectors.Utils.getByTagAndID(self, tag, id);
  for (var i = 0, l = items.length; i < l; i++){
   var item = items[i];
   if (Selectors.Utils.chk(item, uniques)) found.push(item);
  }
  return found;
 },
 
 //大于号>表示子节点的查找
 '>': function(found, self, tag, id, uniques){
  var children = Selectors.Utils.getByTagAndID(self, tag, id);
  for (var i = 0, l = children.length; i < l; i++){
   var child = children[i];
   if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child);
  }
  return found;
 },
 
 //加号+表示后兄弟节点的查找
 '+': function(found, self, tag, id, uniques){
  while ((self = self.nextSibling)){
   if (self.nodeType == 1){
    if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
    break;
   }
  }
  return found;
 },
 
 //波浪号~表示后兄弟节点的查找
 '~': function(found, self, tag, id, uniques){
  
  while ((self = self.nextSibling)){
   if (self.nodeType == 1){
    if (!Selectors.Utils.chk(self, uniques)) break;
    if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
   }
  }
  return found;
 }
 
};

//过滤器
Selectors.Filters = {

 //根据标签过滤
 byTag: function(self, tag){
  return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag));
 },
 
 //根据id过滤
 byID: function(self, id){
  return (!id || (self.id && self.id == id));
 },
 
 //根据CSS类名过滤
 byClass: function(self, klass){
  return (self.className && self.className.contains(klass, ' '));
 },
 
 //根据伪类过滤
 byPseudo: function(self, parser, argument, local){
  return parser.call(self, argument, local);
 },
 
 //根据属性过滤
 byAttribute: function(self, name, operator, value){
  //获取属性值
  var result = Element.prototype.getProperty.call(self, name);
  if (!result) return false;
  if (!operator || value == undefined) return true;
  //属性值运算
  switch (operator){
   //相等
   case '=': return (result == value);
   //包含
   case '*=': return (result.contains(value));
   //打头
   case '^=': return (result.substr(0, value.length) == value);
   //结尾
   case '$=': return (result.substr(result.length - value.length) == value);
   //不等
   case '!=': return (result != value);
   //空格分隔包含
   case '~=': return result.contains(value, ' ');
   //连接符分隔包含
   case '|=': return result.contains(value, '-');
  }
  return false;
 }
 
};

//伪类查找
Selectors.Pseudo = new Hash({
 
 // w3c pseudo selectors
 
 //:empty,匹配不包含文本的节点
 empty: function(){
  return !(this.innerText || this.textContent || '').length;
 },
 
 //:not,匹配非指定标签
 not: function(selector){
  return !Element.match(this, selector);
 },
 
 //:contains,匹配节点内容中包含指定字符的节点
 contains: function(text){
  return (this.innerText || this.textContent || '').contains(text);
 },
 
 //:first-child,匹配第一个节点
 'first-child': function(){
  return Selectors.Pseudo.index.call(this, 0);
 },
 
 //:last-child,匹配最后一个节点
 'last-child': function(){
  var element = this;
  while ((element = element.nextSibling)){
   if (element.nodeType == 1) return false;
  }
  return true;
 },
 
 //:only-child,匹配一个子节点类型全为Element的节点
 'only-child': function(){
  var prev = this;
  while ((prev = prev.previousSibling)){
   if (prev.nodeType == 1) return false;
  }
  var next = this;
  while ((next = next.nextSibling)){
   if (next.nodeType == 1) return false;
  }
  return true;
 },
 
 //:nth-child,匹配第n个节点
 'nth-child': function(argument, local){
  argument = (argument == undefined) ? 'n' : argument;
  var parsed = Selectors.Utils.parseNthArgument(argument);
  //非nth伪类的处理转移
  if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local);
  var count = 0;
  local.positions = local.positions || {};
  var uid = $uid(this);
  //如果没有位置标记的记录
  if (!local.positions[uid]){
   var self = this;
   //查找前面的兄弟节点
   while ((self = self.previousSibling)){
    //忽略非Element节点
    if (self.nodeType != 1) continue;
    count ++;
    var position = local.positions[$uid(self)];
    //如果有标记了位置的兄弟节点,加上位置后即可跳出循环
    if (position != undefined){
     count = position + count;
     break;
    }
   }
   local.positions[uid] = count;
  }
  //a*n + b的判断,可由count = a*n + b推出
  return (local.positions[uid] % parsed.a == parsed.b);
 },
 
 // custom pseudo selectors
 
 //:index,匹配指定索引的节点
 index: function(index){
  var element = this, count = 0;
  //向前步进计算当前索引
  while ((element = element.previousSibling)){
   if (element.nodeType == 1 && ++count > index) return false;
  }
  return (count == index);
 },
 
 //:even,匹配索引为偶数的节点
 even: function(argument, local){
  return Selectors.Pseudo['nth-child'].call(this, '2n+1', local);
 },

 //:odd,匹配索引为奇数的节点
 odd: function(argument, local){
  return Selectors.Pseudo['nth-child'].call(this, '2n', local);
 }
 
});